package main

import (
	"fmt"
	"sync"
	"time"
)

var wg sync.WaitGroup
var primeCount int

// 存入所有数字的方法
func putNum(ch chan int) {
	defer wg.Done()
	for i := 2; i <= 120000; i++ {
		ch <- i
	}
	close(ch)
}

// 存入所有素数的方法
func primeNum(inChannel chan int, primeChannel chan int, exitChannel chan bool) {
	defer wg.Done()
	for num := range inChannel {
		var flag = true
		for i := 2; i < num; i++ {
			if num%i == 0 {
				flag = false
				break
			}
		}
		if flag {
			primeCount++
			primeChannel <- num
		}
	}
	exitChannel <- true
}

// 打印所有素数的方法
func printPrime(ch chan int) {
	defer wg.Done()
	for num := range ch {
		fmt.Println(num)
	}
}

func main() {
	// 开启计时
	var startTime = time.Now()
	// 虽然我们要统计的是1 ~ 120000内的素数，但是我们这里读写时，管道容量为1000也够了
	var inChannel = make(chan int, 1000)
	var primeChannel = make(chan int, 1000)
	var exitChannel = make(chan bool, 16)

	wg.Add(1)
	go putNum(inChannel)

	for i := 0; i < 16; i++ {
		wg.Add(1)
		go primeNum(inChannel, primeChannel, exitChannel)
	}

	wg.Add(1)
	go printPrime(primeChannel)

	wg.Add(1)
	go func() {
		defer wg.Done()
		for i := 0; i < 16; i++ {
			<-exitChannel
		}
		close(primeChannel)
	}()

	wg.Wait()
	close(exitChannel)
	// 结束计时
	var endTime = time.Since(startTime)
	fmt.Println("统计完毕……")
	fmt.Printf("共有素数：%v\n", primeCount)
	fmt.Printf("耗时：%v\n", endTime)
}
